package game;

import element.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import static utils.Constant.*;

/**
 * @author 邓哈哈
 * 2023/2/19 20:34
 * Function:
 * Version 1.0
 */

public class GamePanel extends JFrame {
    //定义窗口尺寸
    int width;
    int height;
    //定义背景图
    BackGround bg;
    //定义红线
    Line line;
    //定义缓存图片
    Image offScreeImage;
    //定义实体类列表(金块+石块)
    ArrayList<MyObject> myObjectList = new ArrayList<>();
    //定义能否放置
    boolean isPlace;
    //定义游戏状态(0-准备中 1-进行中 2-成功 3-失败)
    int state;

    /**
     * 构造器
     *
     * @throws HeadlessException
     */
    public GamePanel(int state) throws HeadlessException {
        //初始化窗口尺寸
        this.width = 768;
        this.height = 1000;
        //初始化背景图
        this.bg = new BackGround();
        //初始化红线
        this.line = new Line(this);
        //初始化能否放置(默认可以放置)
        this.isPlace = true;
        //初始化游戏状态(准备中)
        this.state = state;
        //设置开始时间
        START_TIME = System.currentTimeMillis();
        //初始化金块
        for (int i = 0; i < 10; i++) {
            Gold gold;
            double random = Math.random();
            if (random < 0.3) gold = new GoldSmaller();
            else if (random < 0.7) gold = new Gold();
            else gold = new GoldBigger();
            //放置前遍历所有已放置方块
            for (MyObject myObject : this.myObjectList) {
                //如果重叠
                if (gold.getRec().intersects(myObject.getRec()))
                    //不可放置
                    this.isPlace = false;
            }

            if (this.isPlace) this.myObjectList.add(gold);

            else {
                this.isPlace = true;
                //再放置一遍
                i--;
            }
        }

        //初始化石块
        for (int i = 0; i < 5; i++) {
            Rock rock = new Rock();
            //放置前遍历所有已放置方块
            for (MyObject myObject : this.myObjectList) {
                //如果重叠
                if (rock.getRec().intersects(myObject.getRec()))
                    //不可放置
                    this.isPlace = false;
            }

            if (this.isPlace) this.myObjectList.add(rock);
            else {
                this.isPlace = true;
                //再放置一遍
                i--;
            }
        }

        //初始化答辩
        for (int i = 0; i < 3; i++) {
            Shit shit = new Shit();
            //放置前遍历所有已放置方块
            for (MyObject myObject : this.myObjectList) {
                //如果重叠
                if (shit.getRec().intersects(myObject.getRec()))
                    //不可放置
                    this.isPlace = false;
            }

            if (this.isPlace) this.myObjectList.add(shit);
            else {
                this.isPlace = true;
                //再放置一遍
                i--;
            }
        }

        //初始化头像
        for (int i = 0; i < 2; i++) {
            Head001 head = new Head001();
            //放置前遍历所有已放置方块
            for (MyObject myObject : this.myObjectList) {
                //如果重叠
                if (head.getRec().intersects(myObject.getRec()))
                    //不可放置
                    this.isPlace = false;
            }

            if (this.isPlace) this.myObjectList.add(head);
            else {
                this.isPlace = true;
                //再放置一遍
                i--;
            }
        }

        for (int i = 0; i < 2; i++) {
            Head002 head = new Head002();
            //放置前遍历所有已放置方块
            for (MyObject myObject : this.myObjectList) {
                //如果重叠
                if (head.getRec().intersects(myObject.getRec()))
                    //不可放置
                    this.isPlace = false;
            }

            if (this.isPlace) this.myObjectList.add(head);
            else {
                this.isPlace = true;
                //再放置一遍
                i--;
            }
        }


    }

    /**
     * 窗口启动
     */
    public void launch() {
        //标题
        setTitle("黄金矿工怀旧版");
        //窗口初始大小
        setSize(width, height);
        //使屏幕居中
        setLocationRelativeTo(null);
        //用户不能调整大小
        setResizable(true);
        //使窗口可见
        setVisible(true);
        //使窗口可关闭
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        //监听鼠标点击
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                switch (state) {
                    //游戏准备中
                    case 0:
                        state = 1;
                        break;
                    //游戏进行中
                    case 1:
                        line.mouseClicked(e);
                        break;
                    //游戏成功
                    case 2:
                        break;
                    //游戏失败
                    case 3:
                        break;
                    //其他
                    default:
                        break;
                }
            }
        });

        //重绘
        while (true) {
            repaint();

            this.nextLevel();

            try {
                Thread.sleep(8);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 画板绘制
     *
     * @param g the specified Graphics window
     */
    @Override
    public void paint(Graphics g) {
        //初始化缓存图片
        this.offScreeImage = this.createImage(768, 1000);//尺寸与窗口相当
        //获取缓存画笔
        Graphics gImage = offScreeImage.getGraphics();

        switch (this.state) {
            case 0:
                bg.paintPrepare(gImage);
                break;

            case 1:
                //绘制背景
                bg.paintSelf(gImage);
                //绘制实体类 + 绘制得分
                for (MyObject myObject : this.myObjectList) {
                    myObject.paintSelf(gImage);
                    if (myObject.isAlive()) drawCount(myObject, gImage, myObject.getCount());
                }
                //绘制红线+钩爪
                line.paintSelf(gImage);
                //绘制药水使用提示文字
                if (WATER_FLAG) drawHint(gImage);
                break;

            case 2:
                bg.paintWin(gImage);
                break;

            case 3:
                bg.paintFail(gImage);
                break;

            default:
                break;
        }

        //将缓存区绘制好的图形整个绘制到容器的画布中
        g.drawImage(offScreeImage, 0, 0, null);
    }

    /**
     * 获取MyObjectList
     *
     * @return
     */
    public ArrayList<MyObject> getMyObjectList() {
        return myObjectList;
    }

    /**
     * 下一关
     */
    public void nextLevel() {
        //判断游戏是否结束
        // 1.游戏成功
        if (state == 1 && COUNT >= GOAL_COUNT && TIM > 0) {
            //游戏成功
            state = 2;
            //重置页面元素
            reset();
            //关闭当前窗口
            dispose();
            //开启新窗口
            GamePanel panel = new GamePanel(1);
            panel.launch();
        }
        // 2.游戏失败
        else if (state == 1 && COUNT < GOAL_COUNT && TIM < 1) {
            System.out.println("count = " + COUNT);
            System.out.println("goal = " + GOAL_COUNT);
            System.out.println("tim = " + TIM);
            //游戏失败
            state = 3;
            //重置页面元素
            reset();
            //关闭当前窗口
            dispose();
            //开启新窗口
            GamePanel panel = new GamePanel(1);
            panel.launch();
        }
    }

    /**
     * 重置页面元素
     */
    public void reset() {
        //重置分数
        COUNT = 0;
        //重置目标分数
        GOAL_COUNT = (int) (Math.random() * (135 - 110) + 110);
        //重置药水数量
        WATER_COUNT = 5;
        //重置倒计时(这里随便给了个数字>1, 为的是不被判定为成功和失败, 真正的倒计时在重绘面板后给出)
        TIM = 2;
        //关卡加一
        LEVEL++;
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
